bitkeeper revision 1.676 (400729e82e-mItLcWlTMg37ECD5kFQ)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 16 Jan 2004 00:01:44 +0000 (00:01 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Fri, 16 Jan 2004 00:01:44 +0000 (00:01 +0000)
xl_vbd.c, xl_block.c:
  Fix VBD managament in Xenolinux.

xenolinux-2.4.24-sparse/arch/xeno/drivers/block/xl_block.c
xenolinux-2.4.24-sparse/arch/xeno/drivers/block/xl_vbd.c

index 47aac7e0824fb4ac8c73e58e8455a7a850ff4ad5..085120c75bd54ff7032b71271988f618dcb2200d 100644 (file)
@@ -231,8 +231,8 @@ int xenolinux_block_revalidate(kdev_t dev)
     struct block_device *bd;
     struct gendisk *gd;
     xl_disk_t *disk;
-    unsigned long flags, capacity;
-    int i, rc = 0, disk_nr = MINOR(dev) >> gd->minor_shift;
+    unsigned long capacity;
+    int i, rc = 0;
     
     if ( (bd = bdget(dev)) == NULL )
         return -EINVAL;
@@ -257,15 +257,19 @@ int xenolinux_block_revalidate(kdev_t dev)
         goto out;
     }
 
-    for ( i = gd->max_p - 1; i >= 0; i-- )
+    /* Only reread partition table if VBDs aren't mapped to partitions. */
+    if ( !(gd->flags[MINOR(dev) >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) )
     {
-        invalidate_device(dev+i, 1);
-        gd->part[MINOR(dev+i)].start_sect = 0;
-        gd->part[MINOR(dev+i)].nr_sects   = 0;
-        gd->sizes[MINOR(dev+i)]           = 0;
-    }
+        for ( i = gd->max_p - 1; i >= 0; i-- )
+        {
+            invalidate_device(dev+i, 1);
+            gd->part[MINOR(dev+i)].start_sect = 0;
+            gd->part[MINOR(dev+i)].nr_sects   = 0;
+            gd->sizes[MINOR(dev+i)]           = 0;
+        }
 
-    grok_partitions(gd, disk_nr, gd->max_p, capacity);
+        grok_partitions(gd, MINOR(dev)>>gd->minor_shift, gd->max_p, capacity);
+    }
 
  out:
     up(&bd->bd_sem);
index 795ae3c3aa00c33e025ffc512e920c9132247b54..2237404ffca9203cb10823e6a1894a726e5bfa58 100644 (file)
@@ -244,10 +244,16 @@ static int xlvbd_init_device(xen_disk_t *xd)
          * up partition-table information. Virtual partitions override 
          * 'real' partitions, and the two cannot coexist on a device.
          */
-        if ( gd->sizes[minor & ~(max_part-1)] != 0 )
+        if ( !(gd->flags[minor >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) &&
+             (gd->sizes[minor & ~(max_part-1)] != 0) )
         {
+            /*
+             * Any non-zero sub-partition entries must be cleaned out before
+             * installing 'virtual' partition entries. The two types cannot
+             * coexist, and virtual partitions are favoured.
+             */
             kdev_t dev = device & ~(max_part-1);
-            for ( i = max_part - 1; i >= 0; i-- )
+            for ( i = max_part - 1; i > 0; i-- )
             {
                 invalidate_device(dev+i, 1);
                 gd->part[MINOR(dev+i)].start_sect = 0;
@@ -269,14 +275,15 @@ static int xlvbd_init_device(xen_disk_t *xd)
     }
     else
     {
+        gd->part[minor].nr_sects = xd->capacity;
+        gd->sizes[minor] = xd->capacity>>(BLOCK_SIZE_BITS-9);
+        
         /* Some final fix-ups depending on the device type */
         switch ( XD_TYPE(xd->info) )
         { 
         case XD_TYPE_CDROM:
         case XD_TYPE_FLOPPY: 
         case XD_TYPE_TAPE:
-            gd->part[minor].nr_sects = xd->capacity;
-            gd->sizes[minor] = xd->capacity>>(BLOCK_SIZE_BITS-9);
             gd->flags[minor >> gd->minor_shift] |= GENHD_FL_REMOVABLE; 
             printk(KERN_ALERT 
                    "Skipping partition check on %s /dev/%s\n", 
@@ -323,10 +330,10 @@ static int xlvbd_init_device(xen_disk_t *xd)
  */
 static int xlvbd_remove_device(int device)
 {
-    int i, rc = 0, max_part, minor = MINOR(device);
+    int i, rc = 0, minor = MINOR(device);
     struct gendisk *gd;
     struct block_device *bd;
-    xl_disk_t *disk;
+    xl_disk_t *disk = NULL;
 
     if ( (bd = bdget(device)) == NULL )
         return -1;
@@ -347,15 +354,8 @@ static int xlvbd_remove_device(int device)
         rc = -1;
         goto out;
     }
-
-    if ( IDE_DISK_MAJOR(MAJOR(device)) )
-        max_part = XLIDE_MAX_PART;
-    else if ( SCSI_BLK_MAJOR(MAJOR(device)) )
-        max_part = XLSCSI_MAX_PART;
-    else
-        max_part = XLVBD_MAX_PART;
  
-    if ( (minor & (max_part-1)) != 0 )
+    if ( (minor & (gd->max_p-1)) != 0 )
     {
         /* 1: The VBD is mapped to a partition rather than a whole unit. */
         invalidate_device(device, 1);
@@ -365,19 +365,42 @@ static int xlvbd_remove_device(int device)
 
         /* Clear the consists-of-virtual-partitions flag if possible. */
         gd->flags[minor >> gd->minor_shift] &= ~GENHD_FL_VIRT_PARTNS;
-        for ( i = 0; i < max_part; i++ )
-            if ( gd->sizes[(minor & ~(max_part-1)) + i] != 0 )
+        for ( i = 0; i < gd->max_p; i++ )
+            if ( gd->sizes[(minor & ~(gd->max_p-1)) + i] != 0 )
                 gd->flags[minor >> gd->minor_shift] |= GENHD_FL_VIRT_PARTNS;
+
+        /*
+         * If all virtual partitions are now gone, and a 'whole unit' VBD is
+         * present, then we can try to grok the unit's real partition table.
+         */
+        if ( !(gd->flags[minor >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) &&
+             (gd->sizes[minor & ~(gd->max_p-1)] != 0) &&
+             !(gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE) )
+        {
+            register_disk(gd,
+                          device&~(gd->max_p-1), 
+                          gd->max_p, 
+                          &xlvbd_block_fops,
+                          gd->part[minor&~(gd->max_p-1)].nr_sects);
+        }
     }
     else
     {
-        /* 2: The VBD is mapped to an entire 'unit'. Clear all partitions. */
-        for ( i = max_part - 1; i >= 0; i-- )
+        /*
+         * 2: The VBD is mapped to an entire 'unit'. Clear all partitions.
+         * NB. The partition entries are only cleared if there are no VBDs
+         * mapped to individual partitions on this unit.
+         */
+        i = gd->max_p - 1; /* Default: clear subpartitions as well. */
+        if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS )
+            i = 0; /* 'Virtual' mode: only clear the 'whole unit' entry. */
+        while ( i >= 0 )
         {
             invalidate_device(device+i, 1);
             gd->part[minor+i].start_sect = 0;
             gd->part[minor+i].nr_sects   = 0;
             gd->sizes[minor+i]           = 0;
+            i--;
         }
     }